{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.6.1\n",
      "IPython 6.0.0\n",
      "\n",
      "tensorflow 1.2.0\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p tensorflow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model Zoo -- (Classic) Perceptron"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implementation of the classic Perceptron by Frank Rosenblatt for binary classification (here: 0/1 class labels)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Class label counts: [50 50]\n",
      "X.shape: (100, 2)\n",
      "y.shape: (100,)\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### DATASET\n",
    "##########################\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "data = np.genfromtxt('../data/perceptron_toydata.txt', delimiter='\\t')\n",
    "X, y = data[:, :2], data[:, 2]\n",
    "y = y.astype(np.int)\n",
    "\n",
    "print('Class label counts:', np.bincount(y))\n",
    "print('X.shape:', X.shape)\n",
    "print('y.shape:', y.shape)\n",
    "\n",
    "# Shuffling & train/test split\n",
    "shuffle_idx = np.arange(y.shape[0])\n",
    "shuffle_rng = np.random.RandomState(123)\n",
    "shuffle_rng.shuffle(shuffle_idx)\n",
    "X, y = X[shuffle_idx], y[shuffle_idx]\n",
    "\n",
    "X_train, X_test = X[shuffle_idx[:70]], X[shuffle_idx[70:]]\n",
    "y_train, y_test = y[shuffle_idx[:70]], y[shuffle_idx[70:]]\n",
    "\n",
    "# Normalize (mean zero, unit variance)\n",
    "mu, sigma = X_train.mean(axis=0), X_train.std(axis=0)\n",
    "X_train = (X_train - mu) / sigma\n",
    "X_test = (X_test - mu) / sigma"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x113b8cb70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.scatter(X_train[y_train==0, 0], X_train[y_train==0, 1], label='class 0', marker='o')\n",
    "plt.scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], label='class 1', marker='s')\n",
    "plt.xlabel('feature 1')\n",
    "plt.ylabel('feature 2')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model parameters:\n",
      "\n",
      "Weights:\n",
      " [[ 2.02931881]\n",
      " [ 0.5932976 ]]\n",
      "Bias: [[-1.]]\n",
      "\n",
      "Number of training errors: 0\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "\n",
    "\n",
    "##########################\n",
    "### SETTINGS\n",
    "##########################\n",
    "\n",
    "# Architecture\n",
    "n_features = X.shape[1]\n",
    "\n",
    "\n",
    "##########################\n",
    "### GRAPH DEFINITION\n",
    "##########################\n",
    "\n",
    "g = tf.Graph()\n",
    "with g.as_default():\n",
    "   \n",
    "    # Graph Inputs\n",
    "    features = tf.placeholder(dtype=tf.float32, \n",
    "                              shape=[None, n_features], name='features')\n",
    "    targets = tf.placeholder(dtype=tf.float32, \n",
    "                             shape=[None, 1], name='targets')\n",
    "\n",
    "    # Model Parameters\n",
    "    weights = tf.Variable(tf.zeros(shape=[n_features, 1], \n",
    "                          dtype=tf.float32), name='weights')\n",
    "    bias = tf.Variable([[0.]], dtype=tf.float32, name='bias')\n",
    "    \n",
    "\n",
    "    \n",
    "    # Forward Pass\n",
    "    linear = tf.add(tf.matmul(features, weights), bias, name='linear')\n",
    "    ones = tf.ones(shape=tf.shape(linear)) \n",
    "    zeros = tf.zeros(shape=tf.shape(linear))\n",
    "    prediction = tf.where(condition=tf.less(linear, 0.),\n",
    "                          x=zeros, \n",
    "                          y=ones, \n",
    "                          name='prediction')\n",
    "    \n",
    "    # Backward Pass\n",
    "    errors = targets - prediction\n",
    "    weight_update = tf.assign_add(weights, \n",
    "                                  tf.reshape(errors * features, (n_features, 1)),\n",
    "                                  name='weight_update')\n",
    "    bias_update = tf.assign_add(bias, errors,\n",
    "                                name='bias_update')\n",
    "    \n",
    "    train = tf.group(weight_update, bias_update, name='train')\n",
    "    \n",
    "    saver = tf.train.Saver(name='saver')\n",
    "\n",
    "    \n",
    "    \n",
    "##########################\n",
    "### TRAINING & EVALUATION\n",
    "##########################\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    \n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    \n",
    "    for epoch in range(5):\n",
    "        for example, target in zip(X_train, y_train):\n",
    "            feed_dict = {'features:0': example.reshape(-1, n_features),\n",
    "                         'targets:0': target.reshape(-1, 1)}\n",
    "            _ = sess.run(['train'], feed_dict=feed_dict)\n",
    "\n",
    "\n",
    "    w, b = sess.run(['weights:0', 'bias:0'])    \n",
    "    print('Model parameters:\\n')\n",
    "    print('Weights:\\n', w)\n",
    "    print('Bias:', b)\n",
    "\n",
    "    saver.save(sess, save_path='perceptron')\n",
    "    \n",
    "    pred = sess.run('prediction:0', feed_dict={features: X_train})\n",
    "    errors = np.sum(pred.reshape(-1) != y_train)\n",
    "    print('\\nNumber of training errors:', errors)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\ne5Q2AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1147adcc0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "##########################\n",
    "### 2D Decision Boundary\n",
    "##########################\n",
    "\n",
    "x_min = -2\n",
    "y_min = ( -(w[0] * x_min) / w[1]\n",
    "          -(b[0] / w[1]) )\n",
    "\n",
    "x_max = 2\n",
    "y_max = ( -(w[0] * x_max) / w[1]\n",
    "          -(b[0] / w[1]) )\n",
    "\n",
    "\n",
    "fig, ax = plt.subplots(1, 2, sharex=True, figsize=(7, 3))\n",
    "\n",
    "ax[0].plot([x_min, x_max], [y_min, y_max])\n",
    "ax[1].plot([x_min, x_max], [y_min, y_max])\n",
    "\n",
    "ax[0].scatter(X_train[y_train==0, 0], X_train[y_train==0, 1], label='class 0', marker='o')\n",
    "ax[0].scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], label='class 1', marker='s')\n",
    "\n",
    "ax[1].scatter(X_test[y_test==0, 0], X_test[y_test==0, 1], label='class 0', marker='o')\n",
    "ax[1].scatter(X_test[y_test==1, 0], X_test[y_test==1, 1], label='class 1', marker='s')\n",
    "\n",
    "ax[1].legend(loc='upper left')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
